﻿using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using WPFCABShell.Shell.Interface.Services.Settings;
using WPFCABShell.Shell.Services.Settings;
using Microsoft.Practices.ObjectBuilder;

namespace WPFCABShell.UnitTest.Shell.Services.Settings
{
	[TestFixture]
	public sealed class IsolatedStorageSettingsServiceTest : UnitTest.Shared.UnitTest
	{
		private IsolatedStorageSettingsService _isolatedStorageSettingsService;

		protected override void SetUpCore()
		{
			base.SetUpCore();
			_isolatedStorageSettingsService = new IsolatedStorageSettingsService();
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void GetSettings_ShouldThrowIfNameIsNull()
		{
			_isolatedStorageSettingsService.GetSettings(null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentException), ExpectedMessage = "Name must be a valid file name.")]
		public void GetSettings_ShouldThrowIfInvalidName()
		{
			_isolatedStorageSettingsService.GetSettings("name" + System.IO.Path.GetInvalidFileNameChars()[1]);
		}

		[Test]
		public void GetSettings_ShouldGetSettings()
		{
			ISettings settings1 = _isolatedStorageSettingsService.GetSettings("settings1");
			ISettings settings2 = _isolatedStorageSettingsService["settings2"];

			Assert.IsNotNull(settings1);
			Assert.IsNotNull(settings2);
			Assert.AreSame(settings1, _isolatedStorageSettingsService["settings1"]);
			Assert.AreSame(settings2, _isolatedStorageSettingsService.GetSettings("settings2"));
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Contains_ShouldThrowIfKeyIsNull()
		{
			ISettings settings = GetCleanSettings("settings");
			settings.Contains(null);
		}

		[Test]
		public void Contains_ShouldYieldTrueOnlyIfSettingIsPresent()
		{
			ISettings settings = GetCleanSettings("settings");
			Assert.IsFalse(settings.Contains("key"));
			settings.Add("key", "value");
			Assert.IsTrue(settings.Contains("key"));
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Add_ShouldThrowIfKeyIsNull()
		{
			ISettings settings = GetCleanSettings("settings");
			settings.Add(null, "value");
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Get_ShouldThrowIfKeyIsNull()
		{
			ISettings settings = GetCleanSettings("settings");
			settings.Get(null);
		}

		[Test]
		public void Add_Get_ShouldAllowSettingsToBeStoredAndRetrieved()
		{
			ISettings settings = GetCleanSettings("settings");

			settings.Add("key", "value");
			Assert.AreEqual("value", settings.Get("key"));

			settings["foo"] = "bar";
			Assert.AreEqual("bar", settings["foo"]);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Remove_ShouldThrowIfKeyIsNull()
		{
			ISettings settings = GetCleanSettings("settings");
			settings.Remove(null);
		}

		[Test]
		public void Remove_ShouldRemoveValue()
		{
			ISettings settings = GetCleanSettings("settings");

			settings.Remove("key");
			settings["key"] = "value";
			Assert.IsTrue(settings.Contains("key"));
			settings.Remove("key");
			Assert.IsFalse(settings.Contains("key"));
		}

		#region Supporting Methods

		private ISettings GetCleanSettings(string name)
		{
			ISettings settings = _isolatedStorageSettingsService.GetSettings(name);
			InvokePrivateMethod<object>(settings, "Load");
			GetPrivateMemberValue<IDictionary<string, object>>(settings, "_settings").Clear();
			return settings;
		}

		#endregion
	}
}
